﻿using System;
using System.Runtime.InteropServices;

namespace CANCommunication
{
    #region 设备类型
    public struct tagZLG_DeviceInfo
    {
        public uint device_type;  //设备类型
        public uint channel_count;//设备的通道个数
        public tagZLG_DeviceInfo(uint type, uint count)
        {
            device_type = type;
            channel_count = count;
        }
    };

  
    #endregion

    #region CAN数据帧结构
    /// <summary>
    /// CAN定时发送帧
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_AUTO_TRANSMIT_OBJ
    {
        /// <summary>
        /// 0-禁用，1-使能
        /// </summary>
        public ushort enable;
        /// <summary>
        /// 定时报文索引，从0开始，编号相同则使用最新的一条信息
        /// </summary>
        public ushort index;
        /// <summary>
        /// 发送周期，单位毫秒
        /// </summary>
        public uint interval;
        public tagZCAN_Transmit_Data obj;
    };

    /// <summary>
    /// CANFD定时发送帧结构体
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCANFD_AUTO_TRANSMIT_OBJ
    {
        /// <summary>
        /// 0-禁用，1-使能
        /// </summary>
        public ushort enable;
        /// <summary>
        /// 定时报文索引，从0开始，编号相同则使用最新的一条信息
        /// </summary>
        public ushort index;
        /// <summary>
        /// 发送周期，单位毫秒
        /// </summary>
        public uint interval;
        public tagZCAN_TransmitFD_Data obj;
    };

    /// <summary>
    /// CAN发送报文结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_Transmit_Data
    {
        public can_frame frame;
        /// <summary>
        /// 发送方式
        /// <para>0：正常发送 → 在ID仲裁丢失或发送出现错误时，CAN控制器会自动重发，直到发送成功，或发送超时，或总线关闭</para>
        /// <para>1：单次发送 → 在一些应用中，允许部分数据丢失，但不能出现传输延迟时，自动重发就没有意义了。
        /// 在这些应用中，一般会以固定的时间间隔发送数据，自动重发会导致后面的数据无法发送，出现传输延迟。
        /// 使用单次发送，仲裁丢失或发送错误，CAN控制器不会重发报文</para>
        /// <para>2：自发自收 → 产生一次带自接收特性的正常发送，在发送完成后，可以从接收缓冲区中读到已发送的报文</para>
        /// <para>3：单次自发自收 → 产生一次带自接收特性的单次发送，在发送出错或仲裁丢失不会执行重发。
        /// 在发送完成后，可以从接收缓冲区中读到已发送的报文</para>
        /// </summary>
        public uint transmit_type;
    };

    /// <summary>
    /// CANFD发送报文结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_TransmitFD_Data
    {
        public canfd_frame frame;
        public uint transmit_type;
    };

    /// <summary>
    /// 接收CAN报文结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_Receive_Data
    {
        public can_frame frame;
        /// <summary>
        /// 时间戳，单位微秒，基于设备启动时间。（如果为云设备，则基于1970年1月1日0时0分0秒）
        /// </summary>
        public UInt64 timestamp;
    };
    /// <summary>
    /// 接收CANFD报文结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_ReceiveFD_Data
    {
        public canfd_frame frame;
        public UInt64 timestamp;
    };

    /// <summary>
    /// CAN帧结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct can_frame
    {
        /// <summary>
        /// 帧ID，32位，高3位属于标志位，标志位含义如下：
        /// <para>第31位(最高位)代表扩展帧标志，=0表示标准帧，=1代表扩展帧，宏IS_EFF可获取该标志；</para>
        /// <para>第30位代表远程帧标志，=0表示数据帧，=1表示远程帧，宏IS_RTR可获取该标志；</para>
        /// <para>第29位代表错误帧标准，=0表示CAN帧，=1表示错误帧，目前只能设置为0；</para>
        /// <para>其余位代表实际帧ID值，使用宏MAKE_CAN_ID构造ID，使用宏GET_ID获取ID。</para>
        /// </summary>
        public uint can_id;
        /// <summary>
        /// 数据长度
        /// </summary>
        public byte can_dlc;
        /// <summary>
        /// 对其，忽略
        /// </summary>
        public byte __pad;
        public byte __res0;
        public byte __res1;
        /// <summary>
        /// 报文数据，有效长度为can_dlc。
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] data;
    };

    /// <summary>
    /// CANFD帧结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct canfd_frame
    {
        /// <summary>
        /// 帧ID，32位，高3位属于标志位，标志位含义如下：
        /// <para>第31位(最高位)代表扩展帧标志，=0表示标准帧，=1代表扩展帧，宏IS_EFF可获取该标志；</para>
        /// <para>第30位代表远程帧标志，=0表示数据帧，=1表示远程帧，宏IS_RTR可获取该标志；</para>
        /// <para>第29位代表错误帧标准，=0表示CAN帧，=1表示错误帧，目前只能设置为0；</para>
        /// <para>其余位代表实际帧ID值，使用宏MAKE_CAN_ID构造ID，使用宏GET_ID获取ID。</para>
        /// </summary>
        public uint can_id;
        /// <summary>
        /// 数据长度
        /// </summary>
        public byte len; 
        /// <summary>
        /// 额外标志，比如使用CANFD加速，则设置为宏CANFD_BRS
        /// </summary>
        public byte flags;
        public byte __res0;
        public byte __res1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] data;
    };
    #endregion

    /// <summary>
    /// 3.定义CAN控制器状态的数据类型。
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_CHANNEL_STATUS
    {
        /// <summary>
        /// 中断记录，读操作会清楚中断
        /// </summary>
        public byte errInterrupt;
        /// <summary>
        /// CAN控制器模式寄存器值
        /// </summary>
        public byte regMode;
        /// <summary>
        /// CAN控制器状态寄存器值
        /// </summary>
        public byte regStatus;
        /// <summary>
        /// CAN控制器仲裁丢失寄存器值
        /// </summary>
        public byte regALCapture;
        /// <summary>
        /// CAN控制器错误寄存器值
        /// </summary>
        public byte regECCapture;
        /// <summary>
        /// CAN控制器错误警告限制寄存器值。默认为96
        /// </summary>
        public byte regEWLimit;
        /// <summary>
        /// CAN控制器 接收 错误寄存器值：
        /// <para>0-127 时，为错误主动状态</para>
        /// <para>128-254 时，为错误被动状态</para>
        /// <para>255 时 为总线关闭状态。</para>
        /// </summary>
        public byte regRECounter;
        /// <summary>
        /// CAN控制器 发送 错误寄存器值：
        /// <para>0-127 时，为错误主动状态</para>
        /// <para>128-254 时，为错误被动状态</para>
        /// <para>255 时 为总线关闭状态。</para>
        /// </summary>
        public byte regTECounter;
        public UInt32 Reserved;
    }

    /// <summary>
    /// 4.定义错误信息的数据类型。
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZCAN_CHANNEL_ERR_INFO
    {
        /// <summary>
        /// 错误码
        /// </summary>
        public UInt32 errCode;
        /// <summary>
        /// 当产生的错误中有消极错误时表示为消极错误的错误标识数据
        /// </summary>
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
        public byte[] passive_ErrData;
        /// <summary>
        /// 当产生的错误中有仲裁丢失错误时表示为仲裁丢失错误的错误标识数据
        /// </summary>
        public byte arLost_ErrData;
    }

    #region 5.定义初始化CAN的数据类型

    [StructLayout(LayoutKind.Explicit)]
    public struct tagZLG_CHANNEL_INIT_CONFIG
    {
        /// <summary>
        /// 0:can, 1:canFD
        /// </summary>
        [FieldOffset(0)]
        public uint can_Type; //type:TYPE_CAN TYPE_CANFD
        [FieldOffset(4)]
        public tagZLG_CAN_CONFIG canConfig;
        [FieldOffset(4)]
        public tagZLG_CANFD_CONFIG canFDConfig;
    }
    /// <summary>
    /// CAN配置结构
    /// <para>注：当设备类型为
    /// PCI-5010-U 、 PCI-5020-U 、 USBCAN-E-U 、 USBCAN-2E-U 、 USBCAN-4E-U 、
    /// CANDTU 时，帧过滤 acc_code 和 acc_mask 忽略） 采用 GetIProperty 设置 详见 GetIProperty</para>
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZLG_CAN_CONFIG
    {
        /// <summary>
        /// 设置0
        /// </summary>
        public uint accCode;
        /// <summary>
        /// 设置0xFFFFFFFF（全部接收）
        /// </summary>
        public uint accMask;
        public uint reserved;
        /// <summary>
        /// 滤波方式
        /// <para>0：双滤波</para>
        /// <para>1：单滤波</para>
        /// </summary>
        public byte filter;
        /// <summary>
        /// 忽略，不设置
        /// </summary>
        public byte timing0;
        /// <summary>
        /// 忽略，不设置
        /// </summary>
        public byte timing1;
        /// <summary>
        /// <para>0：正常模式</para>
        /// <para>1：只听模式（只接收，不影响总线）</para>
        /// </summary>
        public byte mode;
    }

    /// <summary>
    /// CANFD配置结构
    /// <para>注：当设备类型为
    /// USBCANFD_100U 、 USBCANFD_200U 、 USBCANFD_MINI 时，帧过滤(acc_code
    /// 和 acc_mask 忽略 采用 GetIProperty 设置 详见 GetIProperty 。</para>
    /// <para>注：当设备类型为
    /// PCIECANFD_100U 、 PCIECANFD_400U 、 MiniPCIeCANFD 、 M.2CANFD 时，模式
    /// mode 在正常模式 0 和只听模式 1 基础上，支持 自发自收模式 2 和单次发送模式 3 。 单次发送模式： CAN
    /// 处于正常模式，但是发送失败时不会进行重发 ，此时 发送超时 无效。</para>
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct tagZLG_CANFD_CONFIG
    {
        public uint accCode;
        public uint accMask;
        /// <summary>
        /// 忽略，不设置
        /// </summary>
        public byte abit_timing;
        /// <summary>
        /// 忽略，不设置
        /// </summary>
        public byte dbit_timing;
        /// <summary>
        /// 波特率预分频因子，设置为0
        /// </summary>
        public uint brp;
        public byte filter;
        /// <summary>
        /// 模式
        /// </summary>
        public byte mode;
        /// <summary>
        /// 数据对齐，不设置
        /// </summary>
        public UInt16 pad;
        public uint reserved;
    }
    #endregion

}
